﻿using System;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;

namespace portDebugAssistant
{
    public partial class Form1 : Form
    {
        bool isOpen = false;                        //打开串口标志位  
        bool isSetProperty = false;                 //属性设置标志
        string newString = null;                    //string类型变量newString， 辅助存储信息
        char[] charreceiveData = null;              //字符数组，用于存储日志文本信息

        public Form1()
        {
            InitializeComponent();              //初始化
            CheckForIllegalCrossThreadCalls = false;//防止跨线程访问
        }

        //窗体加载的时候启动
        private void Form_Load(object sender,EventArgs e)
        {
            this.MaximumSize = this.Size;       //定义最大长度
            this.MinimumSize = this.Size;       //定义最小长度
            this.MaximizeBox = false;           //定义box的最大长度限制为false
            for(int i=0;i<10;i++)               //查找10个串口号，并放入cbxComPort下拉框里
            {
                cbxComPort.Items.Add("COM"+(i+1).ToString());
            }
            cbxComPort.SelectedIndex = 0;
            serialPorts.DataReceived += new SerialDataReceivedEventHandler(post_DataReceived);
        }

        //串口检测功能键
        private void btnCheckCom_Click(object sender,EventArgs e)  
        {
            bool comExistence = false;                               //串口是否存在标志
            cbxComPort.Items.Clear();                                //清空下拉框里的所有串口
            for(int i=0;i<10;i++)                                    //查找10个串口号，并放入下拉框里
            {
                try
                {
                    SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
                    sp.Open();
                    sp.Close();
                    cbxComPort.Items.Add("COM" + (i + 1).ToString());
                    comExistence = true;
                }
                catch
                {
                    continue;
                }
            }
            if(comExistence)
            {
                cbxComPort.SelectedIndex = 0;
            }
            else
            {
                MessageBox.Show("没有找到任何可用串口", "错误提示");
            }
        }

        //检查串口是否被放入的标志
        private bool checkPortSetting()         
        {
            if (cbxComPort.Text.Trim() == "") return false;
            if (cbxBaudRate.Text.Trim() == "") return false;
            return true;
        }

        //设置串口属性
        public void SetPortProperty()           
        {
            serialPorts = new SerialPort();
            serialPorts.PortName = cbxComPort.Text.Trim();
            serialPorts.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim());
            cbxStopbites.Text = cbxStopbites.Text.Trim();
            cbxDatabites.Text = cbxDatabites.Text.Trim();
            cbxReplace.Text = cbxReplace.Text.Trim();     
            serialPorts.ReadTimeout = -1;
            serialPorts.RtsEnable = true;            
            if (sendString.Checked)
            {
                sendByte.Enabled = true;
            }
            else
            {
                sendByte.Enabled = false;
            }
        }

        //接收数据
        private void post_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (receiveString.Checked == true)                   //如果接收模式为字符模式
            {
                string str = serialPorts.ReadExisting();         //读取串口数据
                charreceiveData = str.ToCharArray();                
                txtReceived.AppendText(str + "\r\n");            //接收显示十六进制数据
                txtLog.AppendText("接收到的字符串是" + str + "\r\n");     //显示到日志文件中    
            }
            else if(receiveByte.Checked == true)                    //如果接收模式为十六进制接收
            {
                string str = serialPorts.ReadExisting();            //读取串口数据
                charreceiveData = str.ToCharArray();                //用于转换成十六进制
                string byteString = null;                           //string类型变量,用于存储转换后的十六进制字符串
                foreach (char letter in charreceiveData)
                {
                    int value = Convert.ToInt32(letter);
                    string hexOutput = String.Format("{0:X}", value);
                    byteString += hexOutput + " ";                          //每转换一次再后面加一个空格
                }
                txtReceived.AppendText(byteString);                         //接收十六进制数据       
                txtLog.AppendText("接收到的十六进制是：" + byteString + "\r\n");     //显示到日志文件中
            }
        }

        //打开串口功能键
        private void btnOpenCom_Click(object sender, EventArgs e)     
        {
            if(isOpen == false)
            {
                if(!checkPortSetting())         //检查串口是否被放入
                {
                    MessageBox.Show("串口未设置", "错误提示");
                    return;
                }
                if (isSetProperty == false)     //检查是否设置串口属性
                {
                    SetPortProperty();
                    isSetProperty = true;
                }
                try
                {
                    serialPorts.Open();                 //打开serialPort控件
                    isOpen = true;                      //串口打开    
                    btnOpenCom.Text = "关闭串口";       //此时打开串口按钮会变成关闭串口按钮
                    cbxDatabites.Text = "8";            //数据位默认为8
                    cbxReplace.Text = "None";           //奇偶校验默认为None
                    cbxStopbites.Text = "1";            //停止位默认为1
                    serialPorts.DataReceived += new SerialDataReceivedEventHandler(post_DataReceived); //串口接收处理函数
                    cbxBaudRate.Enabled = false;
                    cbxComPort.Enabled = false;
                    cbxDatabites.Enabled = false;
                    cbxReplace.Enabled = false;
                    cbxStopbites.Enabled = false;                
                }
                catch
                {
                    isSetProperty = false;              //串口属性未设置
                    isOpen = false;                     //串口关闭
                    MessageBox.Show("串口无效或已经被占用", "错误提示");
                }
            }
            else
            {
                try
                {
                    serialPorts.Close();                //关闭serialPort控件
                    isOpen = false;                     //串口关闭
                    isSetProperty = false;              //串口属性未设置
                    btnCheckCom.Text = "打开串口";      //关闭串口按钮变回打开串口按钮
                    cbxBaudRate.Enabled = true;
                    cbxComPort.Enabled = true;
                    cbxDatabites.Enabled = true;
                    cbxReplace.Enabled = true;
                    cbxStopbites.Enabled = true;
                }
                catch
                {

                }
            }
        }

        //发送数据功能键
        private void btnSend_Click(object sender, EventArgs e)            
        {
            if(sendString.Checked == true)            //发送模式为字符串模式
            {
                string Str = txtSend.Text.ToString();  //获取发送文本框里面的数据
                if (receiveString.Checked == true)     //接收模式为字符串模式
                {
                    Str += "\r\n";
                    try
                    {
                        if (Str.Length > 0)                                     //当文本框里的字符长度大于0时才可以发送
                        {
                            txtLog.AppendText("时间" + DateTime.Now + "发送的信息为：" + Str + "\r\n");  //发送数据记录在日志文本框中
                            serialPorts.Write(Str);                             //串口发送数据
                        }
                    }
                    catch 
                    {
                        MessageBox.Show("输入错误", "请重新输入");
                    }
                }
                else if(receiveByte.Checked == true)    //接收模式为十六进制模式
                {
                    byte[] setbyt = Encoding.ASCII.GetBytes(Str);                  //将发送的字符串转换为十六进制
                    try
                    {
                        if (setbyt.Length > 0)                                     //当文本框里的字节长度大于0时才可以发送
                        {
                            txtLog.AppendText("时间" + DateTime.Now + "发送的信息为：" + txtSend.Text + "\r\n");    //发送数据记录在日志文本框中
                            serialPorts.Write(setbyt.ToString());                  //串口发送数据                      
                        }
                    }
                    catch
                    {
                        MessageBox.Show("输入错误，请重新输入！");
                    }
                }
                
            }
            else if(sendString.Checked == false)       //发送模式为十六进制模式
            {
                if(receiveString.Checked == true)      //接收模式为字符串模式
                {
                    try
                    {
                        string hexValues = txtSend.Text;
                        string[] hexValuesSplit = hexValues.Split(' ');          //去掉分隔符
                        foreach (string hex in hexValuesSplit)                   //十六进制转换为字符串
                        {
                            int value = Convert.ToInt32(hex, 16);
                            string stringValue = char.ConvertFromUtf32(value);
                            char charValue = (char)value;
                            newString += stringValue;
                        }
                        txtLog.AppendText("时间" + DateTime.Now + "发送的信息为：" + txtSend.Text + "\r\n");    //发送数据记录在日志文本框中
                        serialPorts.Write(newString);
                        newString = null;
                    }
                    catch
                    {
                        MessageBox.Show("输入错误，请重新输入！");
                    }
                }
                else if(receiveByte.Checked == true)                        //接收模式为十六进制模式
                {
                    byte[] setbyt = Encoding.ASCII.GetBytes(txtSend.Text);  //将发送文本框里的数据存储到setbyt字节数组里
                    try
                    {
                        if (setbyt.Length > 0)                                  //当文本框里的字节长度大于0时才可以发送
                        {
                            txtLog.AppendText("时间" + DateTime.Now + "发送的信息为：" + txtSend.Text + "\r\n");    //发送数据记录在日志文本框中
                            serialPorts.Write(setbyt.ToString());               //串口发送数据                      
                        }
                    }
                    catch
                    {
                        MessageBox.Show("输入错误，请重新输入！");
                    }
                }              
            }
            else
            {
                MessageBox.Show("按钮设置错误", "发送失败");
            }
            txtSend.Clear();     
        }

        //打开文件功能键
        private void btnOpen_Click(object sender, EventArgs e)          
        {
            //打开文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择要传的文件";
            ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
            ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*";
            ofd.ShowDialog();
            //得到选择文件的路径
            txtUrl.Text = ofd.FileName;
        }

        //保存文件功能键
        private void btnSave_Click(object sender, EventArgs e)          
        {           
            //创建文件传输流filestream，保存文件路径为D:/log.txt，Appdend不覆盖，create覆盖
            FileStream file = new FileStream(txtUrl.Text, FileMode.Append, FileAccess.Write);
            StreamWriter streamWriter = new StreamWriter(file);
            //获取时间戳
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
            long t = (DateTime.Now.Ticks - startTime.Ticks) / 10000;    //除10000调整为13位 
            string saveText = txtLog.Text;                              //创建string类型变量saveText，用于存储日志信息
            if (saveText == null)                          
            {
                MessageBox.Show("保存失败", "error");
            }
            else
            {
                MessageBox.Show("保存成功", "true");
            }            
            streamWriter.Write(saveText);                              //把日志文件保存
            file.Flush();                                              //关闭文件传输流
            streamWriter.Close();                                      //关闭写入流
            file.Close();                                              //关闭文件
        }

        //清空文本功能键
        private void btnclear_Click(object sender, EventArgs e)        
        {
            txtSend.Clear();
        }
              
        //实现日志文本框滚动
        private void txtLog_TextChanged(object sender, EventArgs e)
        {
            txtLog.SelectionStart = txtLog.Text.Length;
            txtLog.SelectionLength = 0;
            txtLog.ScrollToCaret();
        }

        //实现接收文本框滚动
        private void txtReceived_TextChanged(object sender, EventArgs e)
        {
            txtReceived.SelectionStart = txtLog.Text.Length;
            txtReceived.SelectionLength = 0;
            txtReceived.ScrollToCaret();
        }
    }
}
